#include <iostream>

//template<typename T>
//void f(const T param) {
//
//}

//template<typename T>
//void f(T const param) {
//
//}

void func(int) {
}

void(*funcptr)(int) = func;
void(*const funcptr1)(int) = func;
//void(const* funcptr2)(int) = func;

using FuncPtr = void(*)(int);
const FuncPtr funcptr2 = func;

using Func = void(int);
const Func& funcRef = func;


//template<typename T>
//void f(T param) {}

template<typename T>
void f(T& param) {}

template<typename T>
void f(T&& param) {}

template<typename T>
void f(T* param) {}

int main() {
	//int a = 0;
	//f(a);

	//int* pa = &a;
	//f(pa);

	int a = 10;
	f(a);
	int* pa = &a;
	f(pa);
	int& ra = a;
	f(ra);
	int&& rra = std::move(a);
	f(rra);

	const int b = 10;
	f(b);
	const int* pb = &b;
	f(pb);
	const int& rb = b;
	f(rb);
	const int&& rrb = std::move(a);
	f(rrb);

	int* const cpa = &a;
	f(cpa);
	const int* const cpca = &a;
	f(cpca);

	int array[2] = { 0, 1 };
	f(array);
	"Hello World";
	f("Hello World");
	int(*arrayptr)[2] = &array;
	f(arrayptr);
	int(&arrayref)[2] = array;
	f(arrayref);

	f(func);
	f(funcptr);
}